package contegor.scire.structure.queries;

import java.util.Collections;
import java.util.List;

import contegor.scire.core.Concept;
import contegor.scire.core.Container;
import contegor.scire.core.Id;
import contegor.scire.core.InfiniteSingletonList;
import contegor.scire.core.Link;
import contegor.scire.core.Link.Flow;
import contegor.scire.core.ReturnPoint;
import contegor.scire.core.ScireException;
import contegor.scire.core.Version;
import contegor.scire.core.queries.And;
import contegor.scire.core.queries.Extensor;
import contegor.scire.core.queries.Filter;
import contegor.scire.core.queries.GetLinksFromSource;
import contegor.scire.core.queries.GetTargetsFromLinks;
import contegor.scire.core.queries.IsConnectedWith;
import contegor.scire.core.queries.Query;
import contegor.scire.core.queries.QueryWithDependencies;
import contegor.scire.core.queries.True;
import contegor.scire.core.queries.WithFlow;
import contegor.scire.structure.Constants;

/**
 * {@link Query} that fetches recursively abstractions of an instance {@link Concept} identified by its {@link Id}.
 * That is, {@link Flow#DOWNSTREAM} links with {@link Constants#TO_BE_SER} links.
 * The result does not include the instance.
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
@Version("$Id$")
public class GetAbstractionsOf extends QueryWithDependencies<Concept, Concept> {
  private static final long serialVersionUID = 4232922463336385397L;

  @SuppressWarnings("unchecked")
  public GetAbstractionsOf(Id id) {
    super(
//        new Extensor<Concept>(new GetTargetsFromLinks(new Filter<Link>(new And<Link>(new IsConnectedWith<Link>(Constants.CONCRETE, WithFlow.DOWNSTREAM), new IsConnectedWith<Link>(Constants.TO_BE_SER, WithFlow.NONE)), new Filter<Link>(WithFlow.DOWNSTREAM, new GetLinksFromSource(id)))))
//          .withIt(new RecursiveQuery<Concept>(id.getParentId(), new CircularGetConceptsUpstreamReplicator(new And<Link>(new IsConnectedWith<Link>(Constants.ABSTRACT, WithFlow.DOWNSTREAM), new IsConnectedWith<Link>(Constants.TO_BE_SER, WithFlow.NONE))), new True<Concept>(), new True<Concept>()))
        new Extensor<Concept>(new GetTargetsFromLinks(new Filter<Link>(new IsConnectedWith<Link>(Constants.TO_BE_SER, WithFlow.NONE), new Filter<Link>(WithFlow.DOWNSTREAM, new GetLinksFromSource(id)))))
          .withIt(new RecursiveQuery<Concept>(id.getParentId(), new CircularGetConceptsUpstreamReplicator(new And<Link>(new IsConnectedWith<Link>(Constants.ABSTRACT, WithFlow.DOWNSTREAM), new IsConnectedWith<Link>(Constants.TO_BE_SER, WithFlow.NONE))), new True<Concept>(), new True<Concept>()))
    );
  }

  @Override
  public List<? extends ReturnPoint<? super Concept>> getDependenciesReturnPoints() {
    if (this.dependencies == null)
      return Collections.emptyList();
    return new InfiniteSingletonList<ReturnPoint<? super Concept>>(this.returnPoint, dependencies.size());
  }

  @Override
  public void process(Container targetContainer) throws ScireException {}

//  @SuppressWarnings("unchecked")
//  public GetAbstractionsOf(Id id) {
//    super(id.getParentId());
//
//    List<Query<Link>> aux = new ArrayList<Query<Link>>(1);
//
//    new GetTargetsFromLinks(new Filter<Link>(new And<Link>(new IsConnectedWith<Link>(Constants.CONCRETE, WithFlow.UPSTREAM), new IsConnectedWith<Link>(Constants.BE_SER, WithFlow.NONE)), new GetLinksFromSource(id)))
//    
//    aux.add(new Extensor<Link,Link>()
//        .withIt(new RecursiveQuery<Link>(id.getParentId(),
//                                         new Replicator<CircularGetLinksUpstream>(CircularGetLinksUpstream.class),
//                                         new And<Link>(new IsConnectedWith<Link>(Constants.ABSTRACT, WithFlow.UPSTREAM), new IsConnectedWith<Link>(Constants.BE_SER, WithFlow.NONE)),
//                                         new And<Link>(new IsConnectedWith<Link>(Constants.ABSTRACT, WithFlow.UPSTREAM), new IsConnectedWith<Link>(Constants.BE_SER, WithFlow.NONE))))
//    );
//    this.dependencies = Collections.unmodifiableList(aux);
//  }
}
